package ar.com.binarit


import org.hibernate.Criteria

import ar.com.binarit.entities.Auto
import ar.com.binarit.entities.Calificacion
import ar.com.binarit.entities.CuentaBancaria
import ar.com.binarit.entities.Equipo
import ar.com.binarit.entities.EstadoCalificacion
import ar.com.binarit.entities.LugarPreferido
import ar.com.binarit.entities.TipoCalificacion
import ar.com.binarit.entities.TipoLugar
import ar.com.binarit.entities.TipoUsuario
import ar.com.binarit.entities.Viaje

class Person {

	transient springSecurityService
	def grailsLinkGenerator

	String username
	String password
	String email
	boolean enabled
	boolean accountExpired
	boolean accountLocked
	boolean passwordExpired
	Date fechaInscripcion
	
	boolean usuarioVerificado = false
	
	String nickname
	String nombre
	String apellido
	String telefono
	String documento
	Integer anioNacimiento
	
	TipoUsuario tipoUsuario
	String imgAvatar
	
	int valorRanking
	
	Auto auto
	Equipo equipo
	
	static hasMany = [
		viajesRealizados : Viaje, viajesQueParticipo : Viaje, //autos:Auto,
		usuariosBloqueados:Person, cuentasBancarias : CuentaBancaria,
		lugaresPreferidos:LugarPreferido, calificaciones : Calificacion
	]
	
	static mappedBy = [viajesQueParticipo:"hinchas", viajesRealizados:"misViajes"]
	//Buen articulo: http://chrisbroadfoot.id.au/2008/07/19/many-to-many-relationship-mapping-with-gorm-grails/


	static constraints = {
		username blank: false, unique: true
		password blank: false
		email (email: true, nullable: false, unique: true)
		tipoUsuario(nullable: false)
		nickname(nullable: true, size:1..100)
		imgAvatar(nullable:true)
		nickname(nullable:true)
		tipoUsuario(nullable: true)
		equipo(nullable:true)
		usuariosBloqueados(nullable:true)
		cuentasBancarias(nullable: true)
		nombre(nullable:true, size:1..100)
		apellido(nullable:true, size:1..100)
		telefono(nullable:true, size:1..100)
		anioNacimiento(nullable:true)
		documento(nullable:true)
		auto(nullable: true)
		calificaciones(nullable: true)
		fechaInscripcion(nullable: true)
	}

	static transients = ['grailsLinkGenerator']
	
	static mapping = {
		password column: '`password`'
		viajesRealizados joinTable: "person_viaje_s"
		lugaresPreferidos lazy: false
		version false
	}

	String toString(){
		"${email}"
	}
	
	def traerDatosRelacionados() {
		tipoUsuario?.descripcion
	}
	
	def agregarViaje(viaje){
		this.addToViajesRealizados(viaje)
	}
	
	def eliminarViaje(viaje){
		this.removeFromViajesRealizados(viaje)
	}
	
	def agregarAuto(auto){
		this.addToAutos(auto)
	}
	
	def eliminarAuto(auto){
		this.removeFromAutos(auto)
	}
	
	def agregarCuenta(cuenta){
		this.addToCuentasBancarias(cuenta)
	}
	
	def eliminarCuenta(cuenta){
		this.removeCuentasBancarias(cuenta)
	}
	def agregarCalificacion(calificacion){
		this.addToCalificaciones(calificacion)
	}
	
	public boolean equals(Object otro) {
		try {
			return username?.equalsIgnoreCase(otro?.username)
		} catch (ClassCastException e) {
			return false
		}
	}
	
	public int hashCode() {
		return username.hashCode()
	}
	Set<Role> getAuthorities() {
		PersonRole.findAllByPerson(this).collect { it.role } as Set
	}

	def beforeInsert() {
		encodePassword()
	}

	def beforeUpdate() {
		if (isDirty('password')) {
			encodePassword()
		}
	}

	protected void encodePassword() {
		if (password){
			password = springSecurityService.encodePassword(password)
		}
	}
	
	boolean validar(){
		if (!this.email || this.email.equals("")){
			this.errors.rejectValue("email", 'default.null.message',['email']as Object[], "");
		}
		
		if (!this.password || this.password.equals("")){
			this.errors.rejectValue("password", 'default.null.message',['password']as Object[], "");
		}

	}
	
//	public getAuto(){
//		if (autos && !autos.isEmpty()){
//			return autos?.last()
//		}
//		return null
//	}
	
	def unirse(viaje){
		this.addToViajesQueParticipo(viaje)
	}
	
	def desunirse(viaje){
		this.removeFromViajesQueParticipo(viaje)
	}
	
	def estaBloqueado(usuario){
		if (!usuario){
			return false
		}
		
		return !usuariosBloqueados.find{user->usuario.id==user.id }
	}
	
	
	def tieneCuentaBancaria(){
		cuentasBancarias && !cuentasBancarias.isEmpty()
	}
	
	def getCuentaBancaria(){
		if (tieneCuentaBancaria()){
			return cuentasBancarias?.last()
		}
		return null
	}
	
	def tieneLugarPreferido(){
		lugaresPreferidos && !lugaresPreferidos.isEmpty()
	}
	
	def tieneCasa(){
		tieneLugarPreferido() && casa.id
	}
	
	def tieneAuto(){
		auto!=null
	}
	
	def getCasa(){
		def lugar = lugaresPreferidos.find{it.tipoLugar.equals(TipoLugar.miCasa())}
		if (!lugar){
			lugar = new LugarPreferido(usuario: this, tipoLugar: TipoLugar.miCasa())
		}
		return lugar
	}
	
	def agregarLugarPreferido(lugar){
		this.addToLugaresPreferidos(lugar)
	}
	
	def eliminarLugarPreferido(lugar){
		this.removeLugaresPreferidos(lugar)
	}
	
	def getMailVerificar(){
		def result = "<a href='" + grailsLinkGenerator.link(controller: 'perfil', action: 'verificarUsuario', absolute: true, params:['email':this.email]) + "'>aqui</a>"
		return result
	}
	
	def esUsuarioVerificado(){
		usuarioVerificado
	}
	
	def getCalificacionesPendientes(){
		this.calificaciones.findAll { calificacion ->
			calificacion.estadoCalificacion.equals(EstadoCalificacion.pendiente())
		}
	}
	
	def getCalificacionesRecibidas(){
		this.calificaciones.findAll { calificacion ->
			calificacion.estadoCalificacion.equals(EstadoCalificacion.cerrado())
		}
	}
	
	String getImgAvatar(){
		//TODO: Eliminar este metodo
		this.imgAvatar ?: "https://twimg0-a.akamaihd.net/profile_images/2909011660/0db5c60b05f09d1941217e8c2811d03e.png"
	}
	
	String getNombreApellido(){
		"$nombre $apellido"
	}
	
	def getCalificacionesPositivas(){
		return Calificacion.createCriteria().list (){
			createAlias('viaje', 'viaje', Criteria.LEFT_JOIN)
			eq("viaje.usuarioCreador", this)
			eq("estadoCalificacion", EstadoCalificacion.cerrado())
			eq("tipoCalificacion", TipoCalificacion.positiva())
		}
	}
	
	def getCalificacionesNeutras(){
		return Calificacion.createCriteria().list (){
			createAlias('viaje', 'viaje', Criteria.LEFT_JOIN)
			eq("viaje.usuarioCreador", this)
			eq("estadoCalificacion", EstadoCalificacion.cerrado())
			eq("tipoCalificacion", TipoCalificacion.neutra())
		}
//		Calificacion.findAllByUsuarioAndEstadoCalificacionAndTipoCalificacion(
//				this, EstadoCalificacion.cerrado(), TipoCalificacion.neutra())
	}
	
	def getCalificacionesNegativas(){
		return Calificacion.createCriteria().list (){
			createAlias('viaje', 'viaje', Criteria.LEFT_JOIN)
			eq("viaje.usuarioCreador", this)
			eq("estadoCalificacion", EstadoCalificacion.cerrado())
			eq("tipoCalificacion", TipoCalificacion.negativa())
		}
//		Calificacion.findAllByUsuarioAndEstadoCalificacionAndTipoCalificacion(
//				this, EstadoCalificacion.cerrado(), TipoCalificacion.negativa())
	}
}
